package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.exception.CustomException;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.common.constants.WemediaConstants;
import com.heima.model.common.dtos.admin.AdminWmNewsDto;
import com.heima.model.common.dtos.admin.AuthDto;
import com.heima.model.common.dtos.app.ArticleDto;
import com.heima.model.common.dtos.common.PageResponseResult;
import com.heima.model.common.dtos.common.ResponseResult;
import com.heima.model.common.dtos.wemedia.NewsUpOrDownDto;
import com.heima.model.common.dtos.wemedia.WmNewsDto;
import com.heima.model.common.dtos.wemedia.WmNewsPageReqDto;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.common.vo.WmNewsVo;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.thread.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.WmNewsTaskService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author Fu319
* @description 针对表【wm_news(自媒体图文内容信息表)】的数据库操作Service实现
* @createDate 2025-04-02 16:36:41
*/
@Service
@Transactional
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService{
    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;
    @Autowired
    private WmMaterialMapper wmMaterialMapper;
    @Autowired
    private WmNewsTaskService wmNewsTaskService;
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private WmNewsAutoScanServiceImpl wmNewsAutoScanServiceImpl;

    /**
     * 自媒体端显示文章信息
     * @param reqDto
     * @return
     */
    @Override
    public ResponseResult listNew(WmNewsPageReqDto reqDto) {
        //检验参数
        if(reqDto.getPage()==null||reqDto.getSize()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        WmUser user = WmThreadLocalUtil.getUser();
        if(user==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //定义分页数据
        IPage<WmNews> iPage=new Page(reqDto.getPage(),reqDto.getSize());
        LambdaQueryWrapper<WmNews> wrapper=new LambdaQueryWrapper<>();
        //设置查询条件
        if(reqDto.getStatus() != null){
            wrapper.eq(WmNews::getStatus,reqDto.getStatus());
        }
        if(reqDto.getKeyword() != null){
            wrapper.like(WmNews::getTitle,reqDto.getKeyword());
        }
        if(reqDto.getChannelId() != null){
            wrapper.eq(WmNews::getChannelId,reqDto.getChannelId());
        }
        if(reqDto.getBeginPubDate() != null&&reqDto.getEndPubDate()!=null){
            wrapper.between(WmNews::getPublishTime,reqDto.getBeginPubDate(),reqDto.getEndPubDate());
        }
        wrapper.orderByDesc(WmNews::getPublishTime);
        //调用mapper获取查询数据
        IPage<WmNews> iPageData = wmNewsMapper.selectPage(iPage, wrapper);
        PageResponseResult pageResponseResult=PageResponseResult
                .builder()
                .currentPage((int) iPageData.getCurrent())
                .total((int) iPageData.getTotal())
                .size((int) iPageData.getSize())
                .build();
        pageResponseResult.setData(iPageData.getRecords());
        pageResponseResult.setErrorMessage(String.valueOf(AppHttpCodeEnum.SUCCESS));
        return pageResponseResult;
    }

    /**
     * 提交文章或保存草稿
     * @param reqDto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult submit(WmNewsDto reqDto) {
        //判断参数是否存在
        if(reqDto == null||reqDto.getContent() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //保存或修改文章
        WmNews wmNews=new WmNews();
        //属性拷贝
        BeanUtils.copyProperties(reqDto,wmNews);
        //封面图片 list ---> String
        if(reqDto.getImages()!=null&& reqDto.getImages().size()>0){
            //数组转字符串
            String imageStr= StringUtils.join(reqDto.getImages(),",");
            wmNews.setImages(imageStr);
        }
        //如果封面为自动 -1
        if(reqDto.getType()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        if(reqDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){
            wmNews.setType(null);
        }

        //如果保存为草稿,则结束此方法
        if(reqDto.getStatus().equals(WmNews.Status.NORMAL.getCode())){
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        //保存或修改文章内容
        saveOrUpdateWmNews(wmNews);
        //如果不为草稿，保存文章内容中的图片与素材表的关联
        //抽取文章内容中的图片
        List<String> materials=ectractUrlInfo(reqDto.getContent());
        if(materials!=null){
            saveRelativeInfoForContent(materials,wmNews.getId(),WemediaConstants.WM_CONTENT_REFERENCE);
        }


        //如果不为草稿，保存文章封面中的图片与素材表的关联,同时判断封面是否设置为自动
        if(reqDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){
            //如果文章内容中没有图片，则设置为0图文章
            if(materials.size()==0){
                wmNews.setType((short)0);
                saveOrUpdateWmNews(wmNews);
                return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
            }else if(materials.size()>0&&materials.size()<3){
                //如果文章中有1-2张图，则设置为单图文章
                List<String> materialOne=new ArrayList<>();
                materialOne.add(materials.get(0));
                wmNews.setType((short)materialOne.size());
                wmNews.setImages(StringUtils.join(materialOne,","));
                saveOrUpdateWmNews(wmNews);
                saveRelativeInfoForContent(materialOne,wmNews.getId(),WemediaConstants.WM_COVER_REFERENCE);
            }else if(materials.size()>=3){
                //如果文章中有3张及以上图片，则设置为3图文章
                List<String> materialThree=new ArrayList<>();
                for (int i = 0; i <3; i++) {
                    materialThree.add(materials.get(i));
                }
                wmNews.setType((short)materialThree.size());
                wmNews.setImages(StringUtils.join(materialThree,","));
                saveOrUpdateWmNews(wmNews);
                saveRelativeInfoForContent(reqDto.getImages(),wmNews.getId(),WemediaConstants.WM_COVER_REFERENCE);
            }
        }
        //审核文章
        //wmNewsAutoScanService.autoScanWmNews(wmNews.getId());
        //先交给延迟服务，审核文章时间即为文章发布时间
        wmNewsTaskService.addNewsTask(wmNews.getId(), wmNews.getPublishTime());
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 修改回显文章信息
     * @param newsId
     * @return
     */
    @Override
    public ResponseResult show(Integer newsId) {
        WmNews wmNews = wmNewsMapper.selectById(newsId);
        if(wmNews==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        if(wmNews.getType()==null){
            wmNews.setType(WemediaConstants.WM_NEWS_TYPE_AUTO);
        }
        return ResponseResult.okResult(wmNews);
    }

    /**
     * 删除文章信息
     * @param newsId
     * @return
     */
    @Override
    public ResponseResult delNews(Integer newsId) {
        //删除文章与素材对应关联
        LambdaQueryWrapper<WmNewsMaterial> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(WmNewsMaterial::getNewsId,newsId);
        wmNewsMaterialMapper.delete(wrapper);
        //获取app端文章信息
        WmNews wmNews = wmNewsMapper.selectById(newsId);
        //删除文章信息
        wmNewsMapper.deleteById(newsId);
        //文章处于未审核，审核不通过，需要人工审核时都可以直接删除，不用更改app端文字是否删除状态
        if(wmNews.getStatus().equals(WmNews.Status.FAIL.getCode())
                ||wmNews.getStatus().equals(WmNews.Status.ADMIN_AUTH.getCode())
                ||wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())){
            return ResponseResult.errorResult(AppHttpCodeEnum.SUCCESS);
        }
        //修改app端已发布文章配置信息
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setArticleId(Long.valueOf(wmNews.getArticleId()));
        apArticleConfig.setIsDelete(1);
        //封装调用feign接口需要的数据
        ArticleDto articleDto = new ArticleDto();
        articleDto.setId(Long.valueOf(newsId));
        articleDto.setApArticleConfig(apArticleConfig);
        //通过kafka来更改app端文章配置信息表中的是否删除字段
        kafkaTemplate.send("article-Topic",JSON.toJSONString(articleDto));
        //调用feign接口将修改状态信息发送到article微服务
        //iArticleClient.saveArticle(articleDto);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * admin端分页显示需要人工审核的文章
     * @param reqDto
     * @return
     */
    @Override
    public ResponseResult listVo(AdminWmNewsDto reqDto) {
        //检验参数
        if(reqDto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        LambdaQueryWrapper<WmNews> wrapper=new LambdaQueryWrapper<>();
        if(reqDto.getStatus() != null){
            wrapper.eq(WmNews::getStatus,reqDto.getStatus());
        }
        if(StringUtils.isNotEmpty(reqDto.getTitle())){
            wrapper.like(WmNews::getTitle,reqDto.getTitle());
        }
        List<WmNewsVo> wmNewsVoList=new ArrayList<>();
        //开启分页查询
        IPage<WmNews> iPage = new Page<>(reqDto.getPage(),reqDto.getSize());
        IPage<WmNews> iPageData = wmNewsMapper.selectPage(iPage,wrapper);
        for (WmNews record : iPageData.getRecords()) {
            WmNewsVo wmNewsVo=new WmNewsVo();
            //属性拷贝
            BeanUtils.copyProperties(record,wmNewsVo);
            WmUser wmUser = wmUserMapper.selectById(wmNewsVo.getUserId());
            //根据文章中的userid找出文章作者并赋值给authorName
            wmNewsVo.setAuthorName(wmUser.getName());
            wmNewsVoList.add(wmNewsVo);
        }
        return ResponseResult.okResult(wmNewsVoList);
    }

    @Override
    public ResponseResult authFail(AuthDto authDto) {
        if(authDto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews wmNews = wmNewsMapper.selectById(authDto.getId());
        //只有当审核状态为3(人工审核时才可以通过或驳回)
        if(wmNews.getStatus()!=WmNews.Status.ADMIN_AUTH.getCode()){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"当前审核状态错误，无法通过或驳回");
        }

        wmNews.setStatus(authDto.getStatus());
        wmNews.setReason(authDto.getTitle());
        wmNewsMapper.updateById(wmNews);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult authPass(AuthDto authDto) {
        //检验参数
        if(authDto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews wmNews = wmNewsMapper.selectById(authDto.getId());
        //只有当审核状态为3(人工审核时才可以通过或驳回)
        if(wmNews.getStatus()!=WmNews.Status.ADMIN_AUTH.getCode()){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"当前审核状态错误，无法通过或驳回");
        }

        wmNews.setStatus(authDto.getStatus());
        wmNewsMapper.updateById(wmNews);
        //调用自动审核中审核成功后操作代码业务层代码
        wmNewsAutoScanServiceImpl.AuthPass(wmNews);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 修改文章上下架信息
     * @param newsUpOrDownDto
     * @return
     */
    @Override
    public ResponseResult downOrUp(NewsUpOrDownDto newsUpOrDownDto) {
        //检验参数
        if(newsUpOrDownDto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //修改上下架状态
        WmNews wmNews = wmNewsMapper.selectById(newsUpOrDownDto.getId());
        if(wmNews!=null){
            wmNews.setEnable(newsUpOrDownDto.getEnable());
        }
        wmNewsMapper.updateById(wmNews);
        //修改app端已发布文章配置信息
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setArticleId(Long.valueOf(wmNews.getArticleId()));
        if(newsUpOrDownDto.getEnable()==0){
            apArticleConfig.setIsDown(1);
        }else if(newsUpOrDownDto.getEnable()==1){
            apArticleConfig.setIsDown(0);
        }
        ArticleDto articleDto = new ArticleDto();
        articleDto.setId(newsUpOrDownDto.getId());
        articleDto.setApArticleConfig(apArticleConfig);
        //通过kafka来更改app端文章配置信息表中的是否上架字段
        kafkaTemplate.send("article-Topic",JSON.toJSONString(articleDto));
        //调用feign接口将修改状态信息发送到article微服务
        //iArticleClient.saveArticle(articleDto);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 保存文章内容中的图片与素材表的关联
     * @param materials
     * @param newsId
     * @param type
     */
    private void saveRelativeInfoForContent(List<String> materials, Integer newsId,Short type) {
        if(!CollectionUtils.isEmpty(materials)){
            LambdaQueryWrapper<WmMaterial> wrapper=new LambdaQueryWrapper<>();
            wrapper.in(WmMaterial::getUrl,materials);
            List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(wrapper);
            //判断是否从素材库取出了素材
            if(wmMaterials==null){
                throw new CustomException(AppHttpCodeEnum.WM_METAIL_INVALID);
            }
            List<Integer> materialIds = wmMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());
            //判断根据条件查询的素材库中的素材数量与真实数量不相同则抛出异常
            if(materials.size()!=wmMaterials.size()){
                throw new CustomException(AppHttpCodeEnum.WM_METAIL_INVALID);
            }
            //把素材和文章关联存入批量表中
            wmNewsMaterialMapper.insertBatch(newsId,materialIds,type);
        }
    }

    /**
     * 提取文章内容中的图片信息
     * @param content
     * @return
     */
    private List<String> ectractUrlInfo(String content) {
        List<Map> maps = JSON.parseArray(content, Map.class);
        List<String> materials = new ArrayList<>();
        for (Map map : maps) {
            if("image".equals(map.get("type"))){
                materials.add(map.get("value").toString());
            }
        }
        return materials;
    }

    /**
     * 新增或修改文章
     * @param wmNews
     */
    private void saveOrUpdateWmNews(WmNews wmNews) {
        //属性补全
        wmNews.setUserId(WmThreadLocalUtil.getUser().getId());
        wmNews.setEnable((short)1);//默认上架
        wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());
        if(wmNews.getId()==null){
            //新增
           saveOrUpdate(wmNews);
        }else{
            //修改
            //先删除以前的所有关于这篇文章与素材的关联
            LambdaQueryWrapper<WmNewsMaterial> wrapper=new LambdaQueryWrapper<>();
            wrapper.eq(WmNewsMaterial::getNewsId,wmNews.getId());
            wmNewsMaterialMapper.delete(wrapper);
            //更新文章
            wmNewsMapper.updateById(wmNews);
        }
    }
}




